package com.blog.cmrpersonalblog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.blog.cmrpersonalblog.entity.ArticleTag;
import com.blog.cmrpersonalblog.entity.ArticleTagRelation;
import com.blog.cmrpersonalblog.mapper.ArticleMapper;
import com.blog.cmrpersonalblog.mapper.ArticleTagMapper;
import com.blog.cmrpersonalblog.mapper.ArticleTagRelationMapper;
import com.blog.cmrpersonalblog.service.ArticleTagRelationService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 文章标签关联服务实现类
 */
@Slf4j
@Service
public class ArticleTagRelationServiceImpl extends ServiceImpl<ArticleTagRelationMapper, ArticleTagRelation> 
        implements ArticleTagRelationService {

   @Resource
    private ArticleTagRelationMapper articleTagRelationMapper;

   @Resource
    private ArticleTagMapper articleTagMapper;

   @Resource
    private ArticleMapper articleMapper;

    @Override
    public List<ArticleTag> getTagsByArticleId(Long articleId) {
        if (articleId == null) {
            return new ArrayList<>();
        }
        return articleTagRelationMapper.selectTagsByArticleId(articleId);
    }

    @Override
    public List<Long> getArticleIdsByTagId(Long tagId) {
        if (tagId == null) {
            return new ArrayList<>();
        }
        return articleTagRelationMapper.selectArticleIdsByTagId(tagId);
    }

    @Override
    public List<Long> getArticleIdsByTagIds(List<Long> tagIds) {
        if (CollectionUtils.isEmpty(tagIds)) {
            return new ArrayList<>();
        }
        return articleTagRelationMapper.selectArticleIdsByTagIds(tagIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean setArticleTags(Long articleId, List<Long> tagIds) {
        try {
            if (articleId == null) {
                log.warn("文章ID为空，无法设置标签");
                return false;
            }

            // 1. 删除现有的标签关联
            removeAllArticleTags(articleId);

            // 2. 如果没有新标签，直接返回
            if (CollectionUtils.isEmpty(tagIds)) {
                // 更新文章的标签数量为0
                syncArticleTagCount(articleId);
                return true;
            }

            // 3. 添加新的标签关联
            return addArticleTags(articleId, tagIds);
        } catch (Exception e) {
            log.error("设置文章标签失败: articleId={}, tagIds={}", articleId, tagIds, e);
            throw new RuntimeException("设置文章标签失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addArticleTags(Long articleId, List<Long> tagIds) {
        try {
            if (articleId == null || CollectionUtils.isEmpty(tagIds)) {
                return false;
            }

            // 1. 过滤已存在的关联
            List<Long> existingTagIds = getTagIdsByArticleId(articleId);
            List<Long> newTagIds = tagIds.stream()
                    .filter(tagId -> !existingTagIds.contains(tagId))
                    .collect(Collectors.toList());

            if (CollectionUtils.isEmpty(newTagIds)) {
                log.info("所有标签已存在，无需添加: articleId={}", articleId);
                return true;
            }

            // 2. 批量插入新的关联
            List<ArticleTagRelation> relations = new ArrayList<>();
            LocalDateTime now = LocalDateTime.now();
            for (Long tagId : newTagIds) {
                ArticleTagRelation relation = new ArticleTagRelation();
                relation.setArticleId(articleId);
                relation.setTagId(tagId);
                relation.setCreateTime(now);
                relations.add(relation);
            }

            int insertCount = articleTagRelationMapper.batchInsert(relations);

            // 3. 批量更新标签使用次数（优化：避免N+1查询）
            if (!newTagIds.isEmpty()) {
                articleTagRelationMapper.batchUpdateTagUseCount(newTagIds, 1);
            }

            // 4. 同步文章标签数量
            syncArticleTagCount(articleId);

            log.info("添加文章标签成功: articleId={}, 新增标签数={}", articleId, insertCount);
            return insertCount > 0;
        } catch (Exception e) {
            log.error("添加文章标签失败: articleId={}, tagIds={}", articleId, tagIds, e);
            throw new RuntimeException("添加文章标签失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeArticleTags(Long articleId, List<Long> tagIds) {
        try {
            if (articleId == null || CollectionUtils.isEmpty(tagIds)) {
                return false;
            }

            // 1. 删除关联
            LambdaQueryWrapper<ArticleTagRelation> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(ArticleTagRelation::getArticleId, articleId)
                   .in(ArticleTagRelation::getTagId, tagIds);
            
            int deleteCount = baseMapper.delete(wrapper);

            // 2. 批量更新标签使用次数（优化：避免N+1查询）
            if (!tagIds.isEmpty()) {
                articleTagRelationMapper.batchUpdateTagUseCount(tagIds, -1);
            }

            // 3. 同步文章标签数量
            syncArticleTagCount(articleId);

            log.info("删除文章标签成功: articleId={}, 删除标签数={}", articleId, deleteCount);
            return deleteCount > 0;
        } catch (Exception e) {
            log.error("删除文章标签失败: articleId={}, tagIds={}", articleId, tagIds, e);
            throw new RuntimeException("删除文章标签失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeAllArticleTags(Long articleId) {
        try {
            if (articleId == null) {
                return false;
            }

            // 1. 获取当前标签ID列表
            List<Long> currentTagIds = getTagIdsByArticleId(articleId);

            // 2. 删除所有关联
            int deleteCount = articleTagRelationMapper.deleteByArticleId(articleId);

            // 3. 批量更新标签使用次数（优化：避免N+1查询）
            if (!currentTagIds.isEmpty()) {
                articleTagRelationMapper.batchUpdateTagUseCount(currentTagIds, -1);
            }

            // 4. 同步文章标签数量
            syncArticleTagCount(articleId);

            log.info("删除文章所有标签成功: articleId={}, 删除标签数={}", articleId, deleteCount);
            return deleteCount >= 0; // 即使没有关联也算成功
        } catch (Exception e) {
            log.error("删除文章所有标签失败: articleId={}", articleId, e);
            throw new RuntimeException("删除文章所有标签失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeAllTagArticles(Long tagId) {
        try {
            if (tagId == null) {
                return false;
            }

            // 1. 获取关联的文章ID列表
            List<Long> articleIds = getArticleIdsByTagId(tagId);

            // 2. 删除所有关联
            int deleteCount = articleTagRelationMapper.deleteByTagId(tagId);

            // 3. 重置标签使用次数
            updateTagUseCount(tagId, -deleteCount);

            // 4. 批量同步所有相关文章的标签数量（优化：避免N+1查询）
            // 注意：这里仍需要循环，因为每篇文章的标签数量不同，无法批量更新
            // 但可以考虑使用异步处理或定时任务来优化
            for (Long articleId : articleIds) {
                syncArticleTagCount(articleId);
            }

            log.info("删除标签所有文章关联成功: tagId={}, 删除关联数={}", tagId, deleteCount);
            return deleteCount >= 0;
        } catch (Exception e) {
            log.error("删除标签所有文章关联失败: tagId={}", tagId, e);
            throw new RuntimeException("删除标签所有文章关联失败: " + e.getMessage());
        }
    }

    @Override
    public int countTagsByArticleId(Long articleId) {
        if (articleId == null) {
            return 0;
        }
        return articleTagRelationMapper.countTagsByArticleId(articleId);
    }

    @Override
    public int countArticlesByTagId(Long tagId) {
        if (tagId == null) {
            return 0;
        }
        return articleTagRelationMapper.countArticlesByTagId(tagId);
    }

    @Override
    public List<ArticleTag> getHotTags(int limit) {
        return articleTagRelationMapper.selectHotTags(limit);
    }

    @Override
    public List<Long> getTagIdsByArticleId(Long articleId) {
        if (articleId == null) {
            return new ArrayList<>();
        }
        return articleTagRelationMapper.selectTagIdsByArticleId(articleId);
    }

    @Override
    public boolean updateTagUseCount(Long tagId, int increment) {
        try {
            if (tagId == null || increment == 0) {
                return false;
            }
            int updateCount = articleTagRelationMapper.updateTagUseCount(tagId, increment);
            return updateCount > 0;
        } catch (Exception e) {
            log.error("更新标签使用次数失败: tagId={}, increment={}", tagId, increment, e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean syncArticleTagCount(Long articleId) {
        try {
            if (articleId == null) {
                return false;
            }
            
            int tagCount = countTagsByArticleId(articleId);
            int updateCount = articleMapper.updateArticleTagCount(articleId, tagCount);
            
            log.debug("同步文章标签数量: articleId={}, tagCount={}", articleId, tagCount);
            return updateCount > 0;
        } catch (Exception e) {
            log.error("同步文章标签数量失败: articleId={}", articleId, e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int syncAllArticleTagCounts() {
        try {
            // 这里需要在ArticleMapper中实现批量更新方法
            return articleMapper.syncAllArticleTagCounts();
        } catch (Exception e) {
            log.error("批量同步文章标签数量失败", e);
            return 0;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean recalculateTagUseCount(Long tagId) {
        try {
            if (tagId == null) {
                return false;
            }
            
            int actualCount = countArticlesByTagId(tagId);
            int updateCount = articleTagMapper.updateTagUseCount(tagId, actualCount);
            
            log.info("重新计算标签使用次数: tagId={}, actualCount={}", tagId, actualCount);
            return updateCount > 0;
        } catch (Exception e) {
            log.error("重新计算标签使用次数失败: tagId={}", tagId, e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int recalculateAllTagUseCounts() {
        try {
            // 这里需要在ArticleTagMapper中实现批量重新计算方法
            return articleTagMapper.recalculateAllTagUseCounts();
        } catch (Exception e) {
            log.error("批量重新计算标签使用次数失败", e);
            return 0;
        }
    }
}